package com.sky.robot.frame.generator;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.builder.Entity;
import com.baomidou.mybatisplus.generator.config.builder.Mapper;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.sky.robot.commons.entity.ResponseDB;
import com.sky.robot.frame.config.GeneratorConfig;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.util.StringUtils;


public class MyAutoGenerator {

    private final ResponseDB bo;

    public MyAutoGenerator(ResponseDB bo) {
        this.bo = bo;
    }

    public void execute() {
        FastAutoGenerator.create(dataSourceBuilder())
                .globalConfig(this::globalConfigBuilder)
                .packageConfig(this::packageConfigBuilder)
                .strategyConfig(this::strategyConfigBuilder)
                .execute();
    }

    public DataSourceConfig.Builder dataSourceBuilder() {
        return new DataSourceConfig.Builder(bo.getDbUrl(), bo.getUsername(), bo.getPassword());
    }

    public void globalConfigBuilder(GlobalConfig.Builder builder) {

        builder.author(bo.getAuthor());

        String outDir = GeneratorConfig.OUTPUT_DIR;
        if (StringUtils.hasText(bo.getOutDir())) {
            outDir = bo.getOutDir();
        }
        builder.outputDir(outDir);

        /*if (!"8".equalsIgnoreCase(bo.getJdkVersion())) {

        }*/

        DateType dateType = DateType.TIME_PACK;
        if ("java.util".equalsIgnoreCase(bo.getDateTimeType())) {
            dateType = DateType.ONLY_DATE;
        }
        builder.dateType(dateType);

        if (BooleanUtils.isTrue(bo.getSwaggerSupport())) {
            builder.enableSwagger();
        }

    }

    public void packageConfigBuilder(PackageConfig.Builder builder) {
        builder
                .parent(bo.getPackageName())
                // builder.moduleName("");
                .controller(bo.getPackageController())
                .entity(bo.getPackageEntity())
                .mapper(bo.getPackageMapper())
                .xml(bo.getPackageMapperXml())
                .service(bo.getPackageService())
                .serviceImpl(bo.getPackageServiceImpl());
    }

    public void strategyConfigBuilder(StrategyConfig.Builder builder) {
        // 其他配置项...
        builder
                // .addFieldPrefix(bo.getFieldPrefixes()) // 作用：设置字段的前缀。生成代码时，会去掉数据库中字段的前缀，生成的实体类字段名称不包含这些前缀。例如，如果数据库字段名是 user_name，且字段前缀为 user_，生成的字段名称会是 name。
                // .addTablePrefix(bo.getTablePrefixes()) // 作用：设置表的前缀。生成代码时，会去掉数据库表名的前缀，生成的类名不包含这些前缀。例如，数据库表名是 t_user，且表前缀是 t_，生成的类名将会是 User。
                .entityBuilder() // 作用：进入实体类生成的配置模式。后续的配置都是针对实体类的生成进行设置。
                .naming(NamingStrategy.underline_to_camel) // 作用：设置命名策略，将数据库中的字段名从下划线命名法（underline）转为驼峰命名法（camel）。例如，数据库字段 user_name 会被生成为实体类中的字段 userName。
                // .formatFileName(bo.getFileNamePatternEntity()) // 作用：设置生成的实体类文件名的格式。你可以通过传入的 bo.getFileNamePatternEntity() 来自定义实体类的文件名，例如可以为每个类名添加后缀或前缀。
                .idType(IdType.ASSIGN_ID) // 作用：设置主键策略。IdType.ASSIGN_ID 表示使用 MyBatis-Plus 的自带主键生成策略，通常是雪花算法自动生成唯一的 ID。
                .logicDeleteColumnName(bo.getFieldLogicDelete()) // 作用：设置逻辑删除字段的名称。指定哪个字段作为逻辑删除字段，逻辑删除的行不会被真正删除，只是将这个字段的值标记为删除状态。
                // .versionColumnName(bo.getFieldVersion()) // 作用：设置乐观锁字段的名称。指定哪个字段用于实现乐观锁机制，避免并发更新时数据冲突。
                // .superClass(bo.getSuperClassName()) // 作用：设置生成的实体类继承的父类。如果你有一个通用的父类，所有实体类都需要继承，你可以通过这项配置来实现继承关系。
                // .addIgnoreColumns(bo.getIgnoreColumns()) // 作用：指定生成实体类时忽略哪些数据库表字段。传入字段列表，生成实体类时这些字段将不会出现在实体类中。
                .mapperBuilder() // 作用：进入 Mapper 层的生成配置模式。后续的配置都是针对 Mapper 接口的生成进行设置。
                // .formatMapperFileName(bo.getFileNamePatternMapper()) // 作用：设置生成的 Mapper 接口文件名的格式。可以自定义 Mapper 接口文件名的命名模式。
                // .formatXmlFileName(bo.getFileNamePatternMapperXml()) // 作用：设置生成的 Mapper XML 文件名的格式。你可以通过传入的 bo.getFileNamePatternMapperXml() 来自定义生成的 XML 文件名。
                .serviceBuilder() // 作用：进入 Service 层的生成配置模式。后续的配置都是针对 Service 接口的生成进行设置。
                // .formatServiceFileName(bo.getFileNamePatternService()) // 作用：设置生成的 Service 接口文件名的格式。可以自定义 Service 接口文件名的命名模式。
                // .formatServiceImplFileName(bo.getFileNamePatternServiceImpl()) // 作用：设置生成的 Service 实现类文件名的格式。可以自定义 Service 实现类文件名的命名模式。
                .controllerBuilder() // 作用：进入 Controller 层的生成配置模式。后续的配置都是针对 Controller 类的生成进行设置。
                .enableRestStyle() // 作用：开启 REST 风格的 Controller。生成的 Controller 类会带有 @RestController 注解，而不是 @Controller，并且所有方法的返回值会默认以 JSON 格式返回。
                .enableHyphenStyle(); // 作用：开启请求路径的下划线转连字符策略。Controller 的 URL 路径会自动将下划线命名法转为连字符命名法（-），例如 user_name 会变成 user-name。

        Entity.Builder entityBuilder = builder.entityBuilder();
        if (BooleanUtils.isTrue(bo.getLombokChainModel())) {
            entityBuilder.enableChainModel();
        }
        if (BooleanUtils.isTrue(bo.getLombokModel())) {
            entityBuilder.enableLombok();
        }
        if (BooleanUtils.isTrue(bo.getColumnConstant())) {
            entityBuilder.enableColumnConstant();
        }
        // 字段注解
        if (BooleanUtils.isTrue(bo.getFieldAnnotation())) {
            entityBuilder.enableTableFieldAnnotation();
        }

        Mapper.Builder mapperBuilder = builder.mapperBuilder();
        if (BooleanUtils.isTrue(bo.getBaseResultMap())) {
            mapperBuilder.enableBaseResultMap();
        }
        if (BooleanUtils.isTrue(bo.getBaseColumnList())) {
            mapperBuilder.enableBaseColumnList();
        }

        // 开启mapper注解
        if (BooleanUtils.isTrue(bo.getMapperAnnotation())) {
            mapperBuilder.enableMapperAnnotation();
        }
    }

}
